﻿/**
* @description c# like string.format
* @param {string} source string
* @param {string} params
* @returns {string}
*/
var framework = {
    format: function (source, params) {
        params = Array.prototype.slice.call(arguments, 1);

        for (var i = 0; i < params.length; i++) {
            source = source.replace(new RegExp("\\{" + i + "\\}", "g"), params[i]);
        }
        
        return source;
    }
};

var console = {
    log: function (object) {
        Console.Log(object);
    },
    error: function(object){
        Console.Error(object);
    },
    pause: function () {
        Console.Pause();
    }
}

var $ = {
    load : function (fileName) {
        xdocument.Load(fileName);
        return xdocument;
    },
    select: function (xPath) {
        if (this == xdocument) {
            return xdocument.Select(xPath);
        } else {
            return xdocument.NodeSelect(this, xPath);
        }
        return xdocument.Select(xPath);
    },
    find: function (call) {
        if (!call) {
            return;
        }
        var length = this.length || this.Count;
        if (!length) {
            return;
        }

        for (var i = 0; i < length; i++) {
            var e = this[i];
            if (call(e, i)) {
                return e;
            }
        }

        return null;
    },
    each: function(call){
        if (!call) {
            return;
        }
        var length = this.length || this.Count;
        if (!length) {
            return;
        }

        for (var i = 0; i < length; i++) {
            var e = this[i];
            call(e, i);
        }
    },
    parent: function(){
        return this.ParentNode;
    },
    txt: function(value){
        if (value) {
            this.InnerText = value; 
        }
        else{
            return this.InnerText;
        }
    },
    attr: function (name, value) {
        if (this.Attributes) {
            var attribute = xdocument.FindAttribute(this.Attributes, name);
            if (attribute) {
                if (value) {
                    attribute.Value = value;
                } else {
                    return attribute.Value;
                }
            } else {
                if (value) {
                    var newAttr = xdocument.CreateXmlAttribute(name);
                    newAttr.Value = value;

                    this.Attributes.Append(newAttr);
                }
            }
        }
    },
    cddata: function (value) {
        if (this.ChildNodes) {
            var child = this.ChildNodes.Item(0);

            if (value) {
                child.Value = value;
            } else {
                return child.Value;
            }
        }
    },
    create: function (name, cddata) {
        if (this != $) {
            throw 'create function not found'
        }

        var element = xdocument.CreateElement(name);
        if (cddata) {
            cddata = xdocument.CreateCDataSection(cddata);
            element.AppendChild(cddata);
        }

        return element;
    },
    append: function (element) {
        if (!checkXmlElementCollectionDupliate(this, element)) {
            return;
        }

        this.AppendChild(element);
    },
    insertBefore: function (newElement, item) {
        if (!checkXmlElementCollectionDupliate(this, newElement)) {
            return;
        }

        var dupliate = findXmlElementCollectionDupliate(this, item);
        if (dupliate) {
            item = dupliate;
        }

        this.InsertBefore(newElement, item);
    },
    insertAfter: function (newElement, item) {
        if (!checkXmlElementCollectionDupliate(this, newElement)) {
            return;
        }

        var dupliate = findXmlElementCollectionDupliate(this, item);
        if (dupliate) {
            item = dupliate;
        }

        this.InsertAfter(newElement, item);
    },
    remove: function(item){
        this.RemoveChild(item);
    },
    save: function(){
        xdocument.Save();
    }
}

function checkXmlElementCollectionDupliate(element, newelement) {
    if (element.ChildNodes.Count > 0)
    {
        for (var i = 0; i < element.ChildNodes.Count;i++)
        {
            var e = element.ChildNodes.Item(i);
            if (e.OuterXml == newelement.OuterXml)
            {
                return false;
            }
        }
    }

    return true;
}

function findXmlElementCollectionDupliate(element, newelement) {
    if (element.ChildNodes.Count > 0) {
        for (var i = 0; i < element.ChildNodes.Count; i++) {
            var e = element.ChildNodes.Item(i);
            if (e.OuterXml == newelement.OuterXml) {
                return e;
            }
        }
    }

    return null;
}

function init() {
    for (var x in $) {
        Object.prototype[x] = $[x];
    }
}

init();

function assert(name, target, expect) {
    if (target !== expect) {
        throw framework.format("{0}:expected and actual value not equal, expected value:{1}, actual value:{2}", name, expect, target);
    }
}